package com.util.servlet;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * <h1>通过模板设计模式实现通用类</h1>
 * <p>凡是需要登陆认证的<code>Servlet</code>都可以继承这个<code>ServletAction</code>
 * <br/>如果请求有响应页面，只需要调用内部类<code>Mapping</code>里的<code>findFoward(url)</code>
 * 这个方法即可,子类只需要对execute()方法实现即可
 * </p>
 * <p>
 * 通过JAVA反射技术对HttpServlet进行简单封装，类似于struts框架，<br/>
 * 页面请求过来的参数名只需要与Action<T> T这个Bean里的变量对应即可,<br/>
 * getForm()就是获得页面传过来的参数[注：当前这个只能传T里的string和int/Integer类型的，<br/>
 * 如果需要更多的类型，请修改这个类]
 *</p>
 * @param T 可以是一个用来接受页面请求的Bean
 * @author <a href="mailto:hou.zhy@neusoft.com">侯振宇</a>
 *
 */
@SuppressWarnings("all")
public abstract class ServletAction<T> extends HttpServlet {
	/**
	 *	子类必需实现这个方法，处理相关的业务
	 * @param request
	 * @param response
	 * @param mapping
	 */
	public abstract void execute(HttpServletRequest request,
			HttpServletResponse response, Mapping mapping);
/**
 * <h1>内部调用类，实现页面跳转功能</h1>
 * 
 * @author <a href="mailto:hou.zhy@neusoft.com">侯振宇</a>
 *
 */
	public class Mapping {
		HttpServletRequest request;
		HttpServletResponse response;

		/**
		 * 构造器
		 * @param request
		 * @param response
		 */
		public Mapping(HttpServletRequest request, HttpServletResponse response) {
			this.request = request;
			this.response = response;
		}

		/**
		 * 页面跳转方法
		 * @param uri 需要跳转的地址,可以传递带参数的URL
		 */
		public void findFoward(String uri) {
			try {
				request.getRequestDispatcher(uri).forward(request, response);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		/**
		 * <h1>通过反射获取<code>Bean</code>对象属性值</h1>
		 * 	<p>该方法将取得form 或 url 对应Bean 的参数值</p>
		 * @return Object form bean 实类对象
		 * @author <a href="mailto:hou.zhy@neusoft.com">侯振宇</a>
		 */
		public T getForm() throws Exception{
			Object object = null; //返回的form bean 实类对象
			Object param=null; //接受为bean参数赋值的对象
			Class<T> clazz = getClazz(); //获取将要操作的bean实类
			try {
				object = clazz.newInstance();
			} catch (Exception e) {
				throw new RuntimeException("Class instance is invalid");
			}
			Field[] fields = clazz.getDeclaredFields();
			if(fields.length > 0){
				for(Field field:fields){
					 param = request.getParameter(field.getName().trim());
					if(!"".equals(param) && param!=null){
						param = param.toString().trim();
						String methodName = "set"+field.getName().substring(0, 1).toUpperCase()+field.getName().substring(1);
						try {
							Method method = clazz.getDeclaredMethod(methodName, field.getType());
							if("Integer".equals(field.getType().getSimpleName())||"int".equals(field.getType().getSimpleName()))
								param = Integer.parseInt(param.toString());
							method.invoke(object, param);
						} catch (Exception e) {
							throw new NoSuchMethodException("method name not found:"+methodName+"\n"+e.getMessage());
						}
					}
				}
			}
			return (T) object;
		}
	}
	/**
	 * 反射获取父类泛型第一个参数
	 * @return Class
	 */
	public Class<T> getClazz(){
		Class<T> clazz = null;
		Type type = getClass().getGenericSuperclass();
		if(type instanceof ParameterizedType){
			 Type[] params = ((ParameterizedType) type).getActualTypeArguments(); 
			 if(params.length>0 && params[0] instanceof Class){
				 clazz = (Class<T>)params[0];
			 }else {
				throw new RuntimeException("Class is null!!");
			}
		}
		return clazz;
	}
	/*
	 * 根据类名取得正在操作的栏目
	 * @param content 写入日志的内容
	 */
	private String setActionName(){
		String currentClazzName = getClass().getSimpleName();
		if("PositionTrailinnQueryServlet".equals(currentClazzName)){
			return "位置跟踪-查询";
		}
		if("PositionTrailinnServlet".equals(currentClazzName)){
			return "位置跟踪-用户进行周期设置定位";
		}
		if("PositionTrailinnUpdateUIServlet".equals(currentClazzName)){
			return "位置跟踪-更新界面";
		}
		if("PositionTrailinnUpdateServlet".equals(currentClazzName)){
			return "位置跟踪-更新数据";
		}
		if("PositionTrailinnDelServlet".equals(currentClazzName)){
			return "位置跟踪-删除数据";
		}
		if("TerminalCountServlet".equals(currentClazzName)){
			return "后台管理-统计相关数据报表";
		}
		if("TerminalCountUIServlet".equals(currentClazzName)){
			return "后台管理-统计报表界面";
		}
		if("PositionCountServlet".equals(currentClazzName)){
			return "定位记录统计";
		}
		if("SmsStatsCountServlet".equals(currentClazzName)){
			return "短信记录统计";
		}
		return currentClazzName;
	}
}
